package game;

import enemy.Enemy;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;

import com.sun.crypto.provider.AESCipher;

import player.Player;
import ui.GameStateSwitcher;

public class Game extends BasicGameState {

	private int mouseX;
	private int mouseY;
	
	private String levelName;
	private Level level;
	private Camera camera;

	private Music bg, bgEndLevel, bgClose;

	public Game(String filename) {
		//super("FSMGS");

	}

	@Override
	public void render(GameContainer gc, StateBasedGame state, Graphics g) throws SlickException {

		level.draw(g, camera);


		//		for(Enemy enemy : enemies) { //TODO render enemies
		//			enemy.draw(g);
		//		}
	}

	@Override
	public void init(GameContainer gc, StateBasedGame state){
		AudioEngine.loadAudio();
	}

	public void loadLevel(GameContainer gc, String levelName) throws SlickException{
		try {
			this.levelName = levelName; 
			level = new Level(new File("resources" + File.separator + "levels" + File.separator + levelName + ".map"));

			camera = new Camera(gc.getWidth(), gc.getHeight(), level.getWidth(), level.getHeight());
			camera.forceCenter(level.getPlayer().getX(), level.getPlayer().getY());
			
			AudioEngine.startBackgroundMusic();
			
		} catch (IOException e) {
			throw new SlickException("Cannot Find required level");
		}
	}

	@Override
	public void update(GameContainer gc, StateBasedGame state, int delta) throws SlickException {
		Player player = level.getPlayer();

		// if player has achieved victory condition, execute victory
		if (level.levelCompleted()){
			success(gc, state);
		} else if (level.levelFailed()){
			failed(gc, state);
		} else {
			Input input = gc.getInput();

			// move camera if left/right shift is held down
			if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)){
				int newMouseX = input.getMouseX();
				int newMouseY = input.getMouseY();
				if(mouseX != -1){
					int dX = newMouseX - mouseX;
					int dY = newMouseY - mouseY;
					camera.forceMoveX(-dX);
					camera.forceMoveY(-dY);
					camera.disableFollowing();
				}
				mouseX = newMouseX;
				mouseY = newMouseY;
			} else if (input.isKeyDown(Input.KEY_R)) {//refocus camera
				camera.enableFollowing();
				mouseX = -1;
				mouseY = -1;
			} else{
				mouseX = -1;
				mouseY = -1;
			}
	
	
			//lets extract player input
			//player.setCrouch(input.isKeyDown(Input.KEY_C));
			player.setSprint(input.isKeyDown(Input.KEY_SPACE));
	
			int inputX = -1;
			int inputY = -1;
			if (input.isKeyDown(Input.KEY_A) || input.isKeyDown(Input.KEY_LEFT)) {
				inputX = Input.KEY_LEFT;
			} else if (input.isKeyDown(Input.KEY_D) || input.isKeyDown(Input.KEY_RIGHT)) {
				inputX = Input.KEY_RIGHT;
			}
			if (input.isKeyDown(Input.KEY_W) || input.isKeyDown(Input.KEY_UP)) {
				inputY = Input.KEY_UP;
			} else if (input.isKeyDown(Input.KEY_S) || input.isKeyDown(Input.KEY_DOWN)) {
				inputY = Input.KEY_DOWN;
			}
			if (inputX != -1 || inputY != -1){
				player.move(inputX, inputY, level);
			}
	
			if(input.isKeyDown(Input.KEY_ESCAPE)) {
				state.enterState(GameStateSwitcher.MENU_STATE, new FadeOutTransition(), new FadeInTransition());
			}
	
			if(inputX != -1 || inputY != -1)
				camera.enableFollowing();
	
			ArrayList<Enemy> enemies = level.getEnemies();
	
			for(Enemy enemy : enemies) {
				enemy.doAction(level);
				enemy.update();
			}
	
			//we need to update the level, enemies and the player
			player.update(level);
	
			camera.update(player);
		}
		
	}

	/**
	 * Execute stuff on victory condition.
	 */
	private void success(GameContainer gc, StateBasedGame state) {
		// do things
		((GameStateSwitcher) state).setSuccess(true);
		
		AudioEngine.startWinMusic();
		// switch state to completion screen
		state.enterState(GameStateSwitcher.COMPLETION_STATE, new FadeOutTransition(),new FadeInTransition());
	}
	
	/**
	 * Execute stuff when you suck at playing
	 */
	private void failed(GameContainer gc, StateBasedGame state) {
		// do things
		((GameStateSwitcher) state).setSuccess(false);
		
		// switch state to completion screen
		state.enterState(GameStateSwitcher.COMPLETION_STATE, new FadeOutTransition(),new FadeInTransition());
	}

	public boolean hasLoadedLevel() {
		return level != null;
	}

	public String getLevelName(){
		return levelName;
	}
	
	public int getLevelNumber(){
		return Integer.parseInt(levelName.substring(5));
	}
	
	/**
	 * Returns state ID for Game state.
	 */
	@Override
	public int getID() {
		return GameStateSwitcher.GAME_STATE;
	}

}
